package com.lc.projects.unit.thread.part05.test1;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeUnit;

//取消任务
public class Test6 {
	public static void main(String[] args) {
		ArrayGenerator generator = new ArrayGenerator();
		int[] array = generator.generateArray(1000);
		TaskManager manager = new TaskManager();
		ForkJoinPool pool = new ForkJoinPool();
		SearchNumberTask task = new SearchNumberTask(array, 0, 1000, 3, manager);
		pool.execute(task);

		pool.shutdown();

		try {
			pool.awaitTermination(1, TimeUnit.DAYS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("Main: finished.");
	}
}

class ArrayGenerator {
	public int[] generateArray(int size) {
		StringBuffer sb = new StringBuffer();
		int[] array = new int[size];
		Random random = new Random();
		for (int i = 0; i < array.length; i++) {
			array[i] = random.nextInt(100);
			sb.append("[" + array[i] + "," + i + "]");
		}

		System.out.println(sb);
		return array;
	}
}

class TaskManager {
	private List<ForkJoinTask<Integer>> tasks;

	public TaskManager() {
		super();
		tasks = new ArrayList<>();
	}

	public void addTask(ForkJoinTask<Integer> task) {
		tasks.add(task);
	}

	public void cancelTask(ForkJoinTask<Integer> cancelTask) {
		for (ForkJoinTask<Integer> task : tasks) {
			if (task != cancelTask) {
				task.cancel(true);
				((SearchNumberTask) task).writeCancelMessage();
			}
		}
	}

}

class SearchNumberTask extends RecursiveTask<Integer> {
	private static final long serialVersionUID = 1L;
	private int[] numbers;
	private int start, end;
	private int number;
	private TaskManager manager;

	public SearchNumberTask(int[] numbers, int start, int end, int number, TaskManager manager) {
		super();
		this.numbers = numbers;
		this.start = start;
		this.end = end;
		this.number = number;
		this.manager = manager;
	}

	@Override
	protected Integer compute() {
		System.out.println("Task:" + start + " : " + end);
		int ret = 0;
		if (end - start > 10) {
			int mid = (start + end) / 2;
			SearchNumberTask s1 = new SearchNumberTask(numbers, start, mid, number, manager);
			SearchNumberTask s2 = new SearchNumberTask(numbers, mid, end, number, manager);
			manager.addTask(s1);
			manager.addTask(s2);
			s1.fork();
			s2.fork();

			int returnValue;
			returnValue = s1.join();
			if (returnValue != -1) {
				return returnValue;
			}
			returnValue = s2.join();
			return returnValue;
		} else {
			ret = lookForNumber();
		}
		return ret;
	}

	public void writeCancelMessage() {
		System.out.println("Task: Cancelled from " + start + " " + end);
	}

	private int lookForNumber() {
		for (int i = start; i < end; i++) {
			if (numbers[i] == number) {
				System.out.println("Task: number " + number + " found in position " + i);
				manager.cancelTask(this);
				return i;
			}

			try {
				TimeUnit.MICROSECONDS.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}
		return -1;

	}
}
